<?php

namespace plugin\cms\app\bll;

use core\attribute\Template;
use Exception;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use plugin\cms\app\validate\Comment as ValidateComment;
use support\Db;
use Throwable;

class Comment
{

    /**
     * 查询一条评论
     *
     * @param integer $id
     * @return array
     */
    public function find(
        int $id
    ): array {
        $info = Db::table('cms_comment')
            ->where('id', '=', $id)
            ->first();
        return $info === null ? [] : get_object_vars($info);
    }

    /**
     * 查询一条评论
     *
     * @param integer $id
     * @return array
     */
    public function findAndSiteid(
        int $id,
        int $siteid
    ): array {
        $info = Db::table('cms_comment')
            ->where('id', '=', $id)
            ->where('siteid', '=', $siteid)
            ->first();
        return $info === null ? [] : get_object_vars($info);
    }

    /**
     * 添加评论
     *
     * @param array $data
     * @return integer
     */
    public function add(array $data): int
    {
        $ValidateComment = new ValidateComment();
        if (!$ValidateComment->check($data)) {
            throw new Exception($ValidateComment->getSimpleError());
        }
        $commentid = 0;
        Db::beginTransaction();
        try {
            $data['createtime'] = date('Y-m-d H:i:s');
            $bllContent = new Content();
            $contentinfo = $bllContent->find($data['contentid'], $data['cid'], $data['siteid']);
            if (!$contentinfo) {
                throw new Exception('内容不存在');
            }
            if ($contentinfo['comment'] != 1) {
                throw new Exception('该文章不允许评论');
            }


            $commentid = Db::table('cms_comment')
                ->insertGetId($data);

            $this->setContentCommentCount($data['contentid'], $data['cid'], $data['siteid']);

            Db::commit();
        } catch (Exception $ex) {
            Db::rollBack();
            throw $ex;
        }
        return $commentid;
    }

    /**
     * 回复评论
     *
     * @param integer $toreplyid 评论ID
     * @param array $data
     * @return integer
     */
    public function reply(int $toreplyid, array $data): int
    {

        $ValidateComment = new ValidateComment();
        if (!$ValidateComment->check($data)) {
            throw new Exception($ValidateComment->getSimpleError());
        }

        Db::beginTransaction();
        try {
            $data['createtime'] = date('Y-m-d H:i:s');
            $commentinfo = $this->find($toreplyid); //针对回复的评论
            if (!$commentinfo) {
                throw new Exception('回复的评论不存在');
            }


            if (
                $commentinfo['cid'] != $data['cid']
                ||
                $commentinfo['contentid'] != $data['contentid']
            ) {
                throw new Exception('参数不正确');
            }

            $data['mainid']     = $commentinfo['mainid'] == 0 ? $commentinfo['id'] : $commentinfo['mainid'];
            $data['toreplyid']  = $toreplyid;
            $data['toreplyuid'] = $commentinfo['uid'];

            if ($commentinfo['mainid'] == 0) {
                $maxsort = Db::table('cms_comment')
                    ->where('cid', '=', $data['cid'])
                    ->where('contentid', '=', $data['contentid'])
                    ->where('siteid', '=', $data['siteid'])
                    ->where('mainid', '=', $commentinfo['id'])
                    ->orderBy('sort', 'desc')
                    ->first();
                $data['sort'] = $maxsort ? bcadd(intval($maxsort->sort), 10, 2) : 10;
            } else {
                $data['sort'] = bcadd($commentinfo['sort'], 0.01, 2);
            }


            //回复评论
            $commentid =  Db::table('cms_comment')
                ->insert($data);


            //设置主评论回复数
            $this->setMainCommentReplayCount($data['mainid']);

            //文章评论数
            $this->setContentCommentCount($data['contentid'], $data['cid'], $data['siteid']);

            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }

        return $commentid;
    }


    /**
     * 设置主评论回复数
     *
     * @param integer $mainid
     * @return void
     */
    public function setMainCommentReplayCount(int $mainid)
    {
        $commentcount = Db::table('cms_comment')
            ->where('mainid', '=', $mainid)
            ->count();

        Db::table('cms_comment')
            ->where('id', '=', $mainid)
            ->update([
                'replycount' => $commentcount,
            ]);
    }

    /**
     * 点赞评论
     *
     * @param integer $commentid 评论ID
     * @param integer $uid 点赞人
     * @return void
     */
    public function doPraise(int $commentid, int $uid)
    {

        Db::beginTransaction();
        try {
            $commentinfo = $this->find($commentid);
            if (!$commentinfo) {
                throw new Exception('评论不存在');
            }

            Db::table('cms_comment_praise')
                ->insert([
                    'commentid'  => $commentid,
                    'uid'        => $uid,
                    'createtime' => date('Y-m-d H:i:s'),
                ]);

            $this->setCommentPraiseCount($commentid);

            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }

    /**
     * 取消点赞
     *
     * @param integer $commentid
     * @param integer $uid
     * @return void
     */
    public function cancelPraise(int $commentid, int $uid)
    {

        Db::beginTransaction();
        try {
            $commentinfo = $this->find($commentid);
            if (!$commentinfo) {
                throw new Exception('评论不存在');
            }

            Db::table('cms_comment_praise')
                ->where('commentid', '=', $commentid)
                ->where('uid', '=', $uid)
                ->delete();
            $this->setCommentPraiseCount($commentid);

            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }


    /**
     * 设置某条评论的点赞数
     *
     * @param integer $commentid
     * @return void
     */
    public function setCommentPraiseCount(int $commentid)
    {
        $count = Db::table('cms_comment_praise')
            ->where('commentid', '=', $commentid)
            ->count();

        Db::table('cms_comment')
            ->where('id', '=', $commentid)
            ->update([
                'praisecount' => $count,
            ]);
    }

    /**
     * 某条文章的评论总数
     *
     * @param integer $contentid
     * @param integer $cid
     * @param integer $siteid
     * @return integer
     */
    #[Template]
    public function contentCommentCount(int $contentid, int $cid, int $siteid): int
    {
        return Db::table('cms_comment')
            ->where('contentid', '=', $contentid)
            ->where('cid', '=', $cid)
            ->where('siteid', '=', $siteid)
            ->count();
    }


    /**
     * 设置文章的评论总数
     *
     * @param integer $contentid
     * @param integer $cid
     * @param integer $siteid
     * @return void
     */
    public function setContentCommentCount(int $contentid, int $cid, int $siteid)
    {

        $bllCategory = new Category();
        $tablename = $bllCategory->getTableName($cid, $siteid);

        $count = $this->contentCommentCount($contentid, $cid, $siteid);

        Db::table($tablename)
            ->where('id', '=', $contentid)
            ->where('cid', '=', $cid)
            ->where('siteid', '=', $siteid)
            ->update([
                'commentcount' => $count,
            ]);
    }

    /**
     * 删除评论
     *
     * @param integer $id
     * @param integer $siteid
     * @return void
     */
    public function delete(int $id, int $siteid)
    {
        Db::beginTransaction();
        try {

            $commentinfo =  $this->findAndSiteid($id, $siteid);
            if (!$commentinfo) {
                throw new Exception('评论不存在');
            }
            $childids = [];
            if ($commentinfo['mainid'] == 0) {
                //查询所有子评论
                $childids = Db::table('cms_comment')
                    ->where('mainid', '=', $commentinfo['id'])
                    ->pluck('id');
            }

            //删除评论
            Db::table('cms_comment')
                ->where('id', '=', $id)
                ->delete();
            //删除评论点赞
            Db::table('cms_comment_praise')
                ->where('commentid', '=', $id)
                ->delete();

            //删除子集评论
            if ($childids) {
                Db::table('cms_comment')
                    ->whereIn('id', $childids)
                    ->delete();

                Db::table('cms_comment_praise')
                    ->whereIn('commentid', $childids)
                    ->delete();
            }



            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }

    /**
     * 某条评论是否点赞过
     *
     * @param integer $commentid
     * @param integer $uid
     * @return boolean
     */
    public function isPraise(int $commentid, int $uid): bool
    {
        return Db::table('cms_comment_praise')
            ->where('commentid', '=', $commentid)
            ->where('uid', '=', $uid)
            ->exists();
    }

    public function paginate(
        int $contentid = 0,
        int $cid = 0,
        int $mainid = 0,
        ?int $siteid = null,
        string $order = 'id desc',
        int $pagesize = 20
    ): LengthAwarePaginator {

        $comments =  Db::table('cms_comment')
            ->where('mainid', '=', $mainid)
            ->where('contentid', '=', $contentid)
            ->where('cid', '=', $cid)
            ->when($siteid !== null, function ($query) use ($siteid) {
                return $query->where('siteid', '=', $siteid);
            })
            ->orderByRaw($order)
            ->paginate($pagesize);

        //获取所有UID 一起查询
        $uids = [];
        foreach ($comments as $key => $comment) {
            $uids[] = $comment->uid;
        }

        $users = [];
        if ($uids) {

            $users = Db::table('frame_user')
                ->leftJoin('frame_user_basicinfo', 'frame_user.id', '=', 'frame_user_basicinfo.uid')
                ->whereIn('frame_user.id', $uids)
                ->get(
                    [
                        'frame_user.*',
                        'frame_user_basicinfo.avatar',
                        'frame_user_basicinfo.name',
                        'frame_user_basicinfo.organcompanyid',
                        'frame_user_basicinfo.organpostid',
                        'frame_user_basicinfo.sex'
                    ]
                )
                ->map(function ($value) {
                    return (array)$value;
                })
                ->toArray();
        }
        if ($users) {
            $users = array_column($users, null, 'id');
        }


        //用户信息填入到评论里
        foreach ($comments as $key => $comment) {
            if (key_exists($comment->uid, $users)) {
                $comments[$key]->user = $users[$comment->uid];
            }

            if (key_exists($comment->toreplyuid, $users)) {
                $comments[$key]->toreplyuser = $users[$comment->toreplyuid];
            }
        }

        return $comments;
    }
}
